package com.wang.factory;


import com.wang.annotation.Autowired;
import com.wang.annotation.Service;
import com.wang.annotation.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by wangq on 2021/7/15.
 */
public class AnnotationFactory {
    private static Map<String, Object> beanMap = new HashMap<>();


    // 读取解析自定义注解
    static {
        System.out.println(">>>>>注解解析工厂开始执行");
        // 扫描所有 有自定义@Service注解的类
        Reflections reflections = new Reflections("com.wang");
        Set<Class<?>> serviceAnnotationTypes = reflections.getTypesAnnotatedWith(Service.class);
        try {
            // 把所有的有自定义@Service注解的类放到beanMap中
            for (Class<?> serviceAnnotationClass : serviceAnnotationTypes) {

                Object instance = serviceAnnotationClass.newInstance();
                String key;
                // 如果注解有value值， key就使用value值，否则使用类名
                String serviceAutowiredValue = serviceAnnotationClass.getAnnotation(Service.class).value();
                if (StringUtils.isNotEmpty(serviceAutowiredValue)) {
                    key = serviceAutowiredValue;
                } else {
                    key = serviceAnnotationClass.getSimpleName();
                }
                beanMap.put(key, instance);
            }

            for (Map.Entry<String, Object> bean : beanMap.entrySet()) {
                Object beanObj = bean.getValue();
                Class<?> beanClass = beanObj.getClass();


                // 把所有类中使用自定义@Autowired注解注入的bean，都赋值到类中
                Field[] fields = beanClass.getDeclaredFields();
                for (Field field : fields) {
                    Autowired autowired = field.getAnnotation(Autowired.class);
                    if (autowired != null && autowired.required()) {
                        Class<?> autowiredClass = field.getType();
                        Method method = beanClass.getMethod("set" + autowiredClass.getSimpleName(), autowiredClass);
                        method.invoke(beanObj, beanMap.get(autowiredClass.getSimpleName()));
                    }
                }

                // 把所有使用自定义@Transactional注解的类，都通过代理工厂来获取他的对象，增强事务
                if (beanClass.isAnnotationPresent(Transactional.class)) {
                    ProxyFactory proxyFactory = (ProxyFactory) beanMap.get("ProxyFactory");
                    beanObj = proxyFactory.getTransactionJdkProxy(beanObj);
                }
                beanMap.put(bean.getKey(), beanObj);
            }


        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println(">>>>>注解解析工厂执行完成");
    }

    // 提供获根据beanId取实例化对象的接口
    public static Object getBeanInstance(String beanId) {
        return beanMap.get(beanId);
    }
}
